1   /*
2    * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.
8    *
9    * This code is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12   * version 2 for more details (a copy is included in the LICENSE file that
13   * accompanied this code).
14   *
15   * You should have received a copy of the GNU General Public License version
16   * 2 along with this work; if not, write to the Free Software Foundation,
17   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18   *
19   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20   * or visit www.oracle.com if you need additional information or have any
21   * questions.
22   */
23  /**
24   * @test
25   * @bug 4052404 4052440 4084688 4092475 4101316 4105828 4107014 4107953 4110613
26   * 4118587 4118595 4122371 4126371 4126880 4135316 4135752 4139504 4139940 4143951
27   * 4147315 4147317 4147552 4335196 4778440 4940539 5010672 6475525 6544471 6627549
28   * 6786276
29   * @summary test Locales
30   */
31  /*
32   *
33   *
34   * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
35   * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
36   *
37   * Portions copyright (c) 2007 Sun Microsystems, Inc.
38   * All Rights Reserved.
39   *
40   * The original version of this source code and documentation
41   * is copyrighted and owned by Taligent, Inc., a wholly-owned
42   * subsidiary of IBM. These materials are provided under terms
43   * of a License Agreement between Taligent and Sun. This technology
44   * is protected by multiple US and International patents.
45   *
46   * This notice and attribution to Taligent may not be removed.
47   * Taligent is a registered trademark of Taligent, Inc.
48   *
49   * Permission to use, copy, modify, and distribute this software
50   * and its documentation for NON-COMMERCIAL purposes and without
51   * fee is hereby granted provided that this copyright notice
52   * appears in all copies. Please refer to the file "copyright.html"
53   * for further important copyright and licensing information.
54   *
55   * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
56   * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
57   * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
58   * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
59   * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
60   * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
61   *
62   */
63  
64  import java.text.*;
65  import java.util.Locale;
66  import java.util.MissingResourceException;
67  import java.util.Date;
68  import java.util.Calendar;
69  import java.io.*;
70  
71  public class LocaleTest extends LocaleTestFmwk {
72      public LocaleTest() {
73      }
74  
75      private int ENGLISH = 0;
76      private int FRENCH = 1;
77      private int CROATIAN = 2;
78      private int GREEK = 3;
79      private int NORWEGIAN = 4;
80      private int ITALIAN = 5;
81      private int DUMMY = 6;
82      private int MAX_LOCALES = 6;
83  
84      private int LANG = 0;
85      private int CTRY = 1;
86      private int VAR = 2;
87      private int NAME = 3;
88      private int LANG3 = 4;
89      private int CTRY3 = 5;
90      private int LCID = 6;
91      private int DLANG_EN = 7;
92      private int DCTRY_EN = 8;
93      private int DVAR_EN = 9;
94      private int DNAME_EN = 10;
95      private int DLANG_FR = 11;
96      private int DCTRY_FR = 12;
97      private int DVAR_FR = 13;
98      private int DNAME_FR = 14;
99      private int DLANG_HR = 15;
100     private int DCTRY_HR = 16;
101     private int DVAR_HR = 17;
102     private int DNAME_HR = 18;
103     private int DLANG_EL = 19;
104     private int DCTRY_EL = 20;
105     private int DVAR_EL = 21;
106     private int DNAME_EL = 22;
107     private int DLANG_ROOT = 23;
108     private int DCTRY_ROOT = 24;
109     private int DVAR_ROOT = 25;
110     private int DNAME_ROOT = 26;
111 
112     private String[][] dataTable = {
113         // language code
114         {   "en",   "fr",   "hr",   "el",   "no",   "it",   "xx"    },
115         // country code
116         {   "US",   "FR",   "HR",   "GR",   "NO",   "",   "YY"    },
117         // variant code
118         {   "",     "",     "",     "",     "NY",   "",   ""    },
119         // full name
120         {   "en_US",    "fr_FR",    "hr_HR",    "el_GR",    "no_NO_NY", "it",   "xx_YY"  },
121         // ISO-3 language
122         {   "eng",  "fra",  "hrv",  "ell",  "nor",  "ita",  ""   },
123         // ISO-3 country
124         {   "USA",  "FRA",  "HRV",  "GRC",  "NOR",  "",     ""   },
125         // LCID (not currently public)
126         {   "0409", "040c", "041a", "0408", "0814", "",     ""  },
127 
128         // display language (English)
129         {   "English",  "French",   "Croatian", "Greek",    "Norwegian",    "Italian",  "xx" },
130         // display country (English)
131         {   "United States",    "France",   "Croatia",  "Greece",   "Norway",   "",     "YY" },
132         // display variant (English)
133         {   "",     "",     "",     "",     "Nynorsk",   "",     ""},
134         // display name (English)
135         // Updated no_NO_NY English display name for new pattern-based algorithm
136         // (part of Euro support).
137         {   "English (United States)", "French (France)", "Croatian (Croatia)", "Greek (Greece)", "Norwegian (Norway,Nynorsk)", "Italian", "xx (YY)" },
138 
139         // display langage (French)
140         {   "anglais",  "fran\u00e7ais",   "croate", "grec",    "norv\u00e9gien",    "italien", "xx" },
141         // display country (French)
142         {   "Etats-Unis",    "France",   "Croatie",  "Gr\u00e8ce",   "Norv\u00e8ge", "",     "YY" },
143         // display variant (French)
144         {   "",     "",     "",     "",     "",     "",    "" },
145         // display name (French)
146         {   "anglais (Etats-Unis)", "fran\u00e7ais (France)", "croate (Croatie)", "grec (Gr\u00e8ce)", "norv\u00e9gien (Norv\u00e8ge,Nynorsk)", "italien", "xx (YY)" },
147 
148         // display langage (Croatian)
149         {   "",  "", "hrvatski", "",    "", "", "xx" },
150         // display country (Croatian)
151         {   "",    "",   "Hrvatska",  "",   "", "", "YY" },
152         // display variant (Croatian)
153         {   "",     "",     "",     "",     "", "", ""},
154         // display name (Croatian)
155         {   "", "", "hrvatski (Hrvatska)", "", "", "", "xx (YY)" },
156 
157         // display langage (Greek)
158         {   "\u0391\u03b3\u03b3\u03bb\u03b9\u03ba\u03ac",  "\u0393\u03b1\u03bb\u03bb\u03b9\u03ba\u03ac", "\u039a\u03c1\u03bf\u03b1\u03c4\u03b9\u03ba\u03ac", "\u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac",    "\u039d\u03bf\u03c1\u03b2\u03b7\u03b3\u03b9\u03ba\u03ac", "\u0399\u03c4\u03b1\u03bb\u03b9\u03ba\u03ac", "xx" },
159         // display country (Greek)
160         {   "\u0397\u03bd\u03c9\u03bc\u03ad\u03bd\u03b5\u03c2 \u03a0\u03bf\u03bb\u03b9\u03c4\u03b5\u03af\u03b5\u03c2",    "\u0393\u03b1\u03bb\u03bb\u03af\u03b1",   "\u039a\u03c1\u03bf\u03b1\u03c4\u03af\u03b1",  "\u0395\u03bb\u03bb\u03ac\u03b4\u03b1",   "\u039d\u03bf\u03c1\u03b2\u03b7\u03b3\u03af\u03b1", "", "YY" },
161         // display variant (Greek)
162         {   "",     "",     "",     "",     "", "", "" },
163         // display name (Greek)
164         {   "\u0391\u03b3\u03b3\u03bb\u03b9\u03ba\u03ac (\u0397\u03bd\u03c9\u03bc\u03ad\u03bd\u03b5\u03c2 \u03a0\u03bf\u03bb\u03b9\u03c4\u03b5\u03af\u03b5\u03c2)", "\u0393\u03b1\u03bb\u03bb\u03b9\u03ba\u03ac (\u0393\u03b1\u03bb\u03bb\u03af\u03b1)", "\u039a\u03c1\u03bf\u03b1\u03c4\u03b9\u03ba\u03ac (\u039a\u03c1\u03bf\u03b1\u03c4\u03af\u03b1)", "\u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac (\u0395\u03bb\u03bb\u03ac\u03b4\u03b1)", "\u039d\u03bf\u03c1\u03b2\u03b7\u03b3\u03b9\u03ba\u03ac (\u039d\u03bf\u03c1\u03b2\u03b7\u03b3\u03af\u03b1,Nynorsk)", "\u0399\u03c4\u03b1\u03bb\u03b9\u03ba\u03ac", "xx (YY)" },
165 
166         // display langage (<root>)
167         {   "English",  "French",   "Croatian", "Greek",    "Norwegian",  "Italian",  "xx" },
168         // display country (<root>)
169         {   "United States",    "France",   "Croatia",  "Greece",   "Norway",  "",     "YY" },
170         // display variant (<root>)
171         {   "",     "",     "",     "",     "Nynorsk",   "",     ""},
172         // display name (<root>)
173         {   "English (United States)", "French (France)", "Croatian (Croatia)", "Greek (Greece)", "Norwegian (Norway,Nynorsk)", "Italian", "xx (YY)" },
174     };
175 
176     public static void main(String[] args) throws Exception {
177         new LocaleTest().run(args);
178     }
179 
180     public void TestBasicGetters() {
181         for (int i = 0; i <= MAX_LOCALES; i++) {
182             Locale testLocale = new Locale(dataTable[LANG][i], dataTable[CTRY][i], dataTable[VAR][i]);
183             logln("Testing " + testLocale + "...");
184 
185             if (!testLocale.getLanguage().equals(dataTable[LANG][i]))
186                 errln("  Language code mismatch: " + testLocale.getLanguage() + " versus "
187                             + dataTable[LANG][i]);
188             if (!testLocale.getCountry().equals(dataTable[CTRY][i]))
189                 errln("  Country code mismatch: " + testLocale.getCountry() + " versus "
190                             + dataTable[CTRY][i]);
191             if (!testLocale.getVariant().equals(dataTable[VAR][i]))
192                 errln("  Variant code mismatch: " + testLocale.getVariant() + " versus "
193                             + dataTable[VAR][i]);
194             if (!testLocale.toString().equals(dataTable[NAME][i]))
195                 errln("  Locale name mismatch: " + testLocale.toString() + " versus "
196                             + dataTable[NAME][i]);
197         }
198 
199         logln("Same thing without variant codes...");
200         for (int i = 0; i <= MAX_LOCALES; i++) {
201             Locale testLocale = new Locale(dataTable[LANG][i], dataTable[CTRY][i]);
202             logln("Testing " + testLocale + "...");
203 
204             if (!testLocale.getLanguage().equals(dataTable[LANG][i]))
205                 errln("  Language code mismatch: " + testLocale.getLanguage() + " versus "
206                             + dataTable[LANG][i]);
207             if (!testLocale.getCountry().equals(dataTable[CTRY][i]))
208                 errln("  Country code mismatch: " + testLocale.getCountry() + " versus "
209                             + dataTable[CTRY][i]);
210             if (!testLocale.getVariant().equals(""))
211                 errln("  Variant code mismatch: " + testLocale.getVariant() + " versus \"\"");
212         }
213     }
214 
215     public void TestSimpleResourceInfo() {
216         for (int i = 0; i <= MAX_LOCALES; i++) {
217             if (dataTable[LANG][i].equals("xx"))
218                 continue;
219 
220             Locale testLocale = new Locale(dataTable[LANG][i], dataTable[CTRY][i], dataTable[VAR][i]);
221             logln("Testing " + testLocale + "...");
222 
223             if (!testLocale.getISO3Language().equals(dataTable[LANG3][i]))
224                 errln("  ISO-3 language code mismatch: " + testLocale.getISO3Language()
225                             + " versus " + dataTable[LANG3][i]);
226             if (!testLocale.getISO3Country().equals(dataTable[CTRY3][i]))
227                 errln("  ISO-3 country code mismatch: " + testLocale.getISO3Country()
228                             + " versus " + dataTable[CTRY3][i]);
229 /*
230             // getLCID() is currently private
231             if (!String.valueOf(testLocale.getLCID()).equals(dataTable[LCID][i]))
232                 errln("  LCID mismatch: " + testLocale.getLCID() + " versus "
233                             + dataTable[LCID][i]);
234 */
235         }
236     }
237 
238     /*
239      * @bug 4101316
240      * @bug 4084688 (This bug appears to be a duplicate of something, because it was fixed
241      *              between 1.1.5 and 1.1.6, but I included a new test for it anyway)
242      * @bug 4052440 Stop falling back to the default locale.
243      */
244     public void TestDisplayNames() {
245         Locale  saveDefault = Locale.getDefault();
246         Locale  english = new Locale("en", "US");
247         Locale  french = new Locale("fr", "FR");
248         Locale  croatian = new Locale("hr", "HR");
249         Locale  greek = new Locale("el", "GR");
250 
251         Locale.setDefault(english);
252         logln("With default = en_US...");
253         logln("  In default locale...");
254         doTestDisplayNames(null, DLANG_EN, false);
255         logln("  In locale = en_US...");
256         doTestDisplayNames(english, DLANG_EN, false);
257         logln("  In locale = fr_FR...");
258         doTestDisplayNames(french, DLANG_FR, false);
259         logln("  In locale = hr_HR...");
260         doTestDisplayNames(croatian, DLANG_HR, false);
261         logln("  In locale = el_GR...");
262         doTestDisplayNames(greek, DLANG_EL, false);
263 
264         Locale.setDefault(french);
265         logln("With default = fr_FR...");
266         logln("  In default locale...");
267         doTestDisplayNames(null, DLANG_FR, true);
268         logln("  In locale = en_US...");
269         doTestDisplayNames(english, DLANG_EN, true);
270         logln("  In locale = fr_FR...");
271         doTestDisplayNames(french, DLANG_FR, true);
272         logln("  In locale = hr_HR...");
273         doTestDisplayNames(croatian, DLANG_HR, true);
274         logln("  In locale = el_GR...");
275         doTestDisplayNames(greek, DLANG_EL, true);
276 
277         Locale.setDefault(saveDefault);
278     }
279 
280     private void doTestDisplayNames(Locale inLocale, int compareIndex, boolean defaultIsFrench) {
281         if (defaultIsFrench && !Locale.getDefault().getLanguage().equals("fr"))
282             errln("Default locale should be French, but it's really " + Locale.getDefault().getLanguage());
283         else if (!defaultIsFrench && !Locale.getDefault().getLanguage().equals("en"))
284             errln("Default locale should be English, but it's really " + Locale.getDefault().getLanguage());
285 
286         for (int i = 0; i <= MAX_LOCALES; i++) {
287             Locale testLocale = new Locale(dataTable[LANG][i], dataTable[CTRY][i], dataTable[VAR][i]);
288             logln("  Testing " + testLocale + "...");
289 
290             String  testLang;
291             String  testCtry;
292             String  testVar;
293             String  testName;
294 
295             if (inLocale == null) {
296                 testLang = testLocale.getDisplayLanguage();
297                 testCtry = testLocale.getDisplayCountry();
298                 testVar = testLocale.getDisplayVariant();
299                 testName = testLocale.getDisplayName();
300             }
301             else {
302                 testLang = testLocale.getDisplayLanguage(inLocale);
303                 testCtry = testLocale.getDisplayCountry(inLocale);
304                 testVar = testLocale.getDisplayVariant(inLocale);
305                 testName = testLocale.getDisplayName(inLocale);
306             }
307 
308             String  expectedLang;
309             String  expectedCtry;
310             String  expectedVar;
311             String  expectedName;
312 
313             expectedLang = dataTable[compareIndex][i];
314             if (expectedLang.equals("") && defaultIsFrench)
315                 expectedLang = dataTable[DLANG_EN][i];
316             if (expectedLang.equals(""))
317                 expectedLang = dataTable[DLANG_ROOT][i];
318 
319             expectedCtry = dataTable[compareIndex + 1][i];
320             if (expectedCtry.equals("") && defaultIsFrench)
321                 expectedCtry = dataTable[DCTRY_EN][i];
322             if (expectedCtry.equals(""))
323                 expectedCtry = dataTable[DCTRY_ROOT][i];
324 
325             expectedVar = dataTable[compareIndex + 2][i];
326             if (expectedVar.equals("") && defaultIsFrench)
327                 expectedVar = dataTable[DVAR_EN][i];
328             if (expectedVar.equals(""))
329                 expectedVar = dataTable[DVAR_ROOT][i];
330 
331             expectedName = dataTable[compareIndex + 3][i];
332             if (expectedName.equals("") && defaultIsFrench)
333                 expectedName = dataTable[DNAME_EN][i];
334             if (expectedName.equals(""))
335                 expectedName = dataTable[DNAME_ROOT][i];
336 
337             if (!testLang.equals(expectedLang))
338                 errln("Display language mismatch: " + testLang + " versus " + expectedLang);
339             if (!testCtry.equals(expectedCtry))
340                 errln("Display country mismatch: " + testCtry + " versus " + expectedCtry);
341             if (!testVar.equals(expectedVar))
342                 errln("Display variant mismatch: " + testVar + " versus " + expectedVar);
343             if (!testName.equals(expectedName))
344                 errln("Display name mismatch: " + testName + " versus " + expectedName);
345         }
346     }
347 
348     public void TestSimpleObjectStuff() {
349         Locale  test1 = new Locale("aa", "AA");
350         Locale  test2 = new Locale("aa", "AA");
351         Locale  test3 = (Locale)test1.clone();
352         Locale  test4 = new Locale("zz", "ZZ");
353 
354         if (test1 == test2 || test1 == test3 || test1 == test4 || test2 == test3)
355             errln("Some of the test variables point to the same locale!");
356 
357         if (test3 == null)
358             errln("clone() failed to produce a valid object!");
359 
360         if (!test1.equals(test2) || !test1.equals(test3) || !test2.equals(test3))
361             errln("clone() or equals() failed: objects that should compare equal don't");
362 
363         if (test1.equals(test4) || test2.equals(test4) || test3.equals(test4))
364             errln("equals() failed: objects that shouldn't compare equal do");
365 
366         int hash1 = test1.hashCode();
367         int hash2 = test2.hashCode();
368         int hash3 = test3.hashCode();
369 
370         if (hash1 != hash2 || hash1 != hash3 || hash2 != hash3)
371             errln("hashCode() failed: objects that should have the same hash code don't");
372     }
373 
374     /**
375      * @bug 4011756 4011380
376      */
377     public void TestISO3Fallback() {
378         Locale test = new Locale("xx", "YY", "");
379         boolean gotException = false;
380         String result = "";
381 
382         try {
383             result = test.getISO3Language();
384         }
385         catch (MissingResourceException e) {
386             gotException = true;
387         }
388         if (!gotException)
389             errln("getISO3Language() on xx_YY returned " + result + " instead of throwing an exception");
390 
391         gotException = false;
392         try {
393             result = test.getISO3Country();
394         }
395         catch (MissingResourceException e) {
396             gotException = true;
397         }
398         if (!gotException)
399             errln("getISO3Country() on xx_YY returned " + result + " instead of throwing an exception");
400     }
401 
402     /**
403      * @bug 4106155 4118587
404      */
405     public void TestGetLangsAndCountries() {
406         // It didn't seem right to just do an exhaustive test of everything here, so I check
407         // for the following things:
408         // 1) Does each list have the right total number of entries?
409         // 2) Does each list contain certain language and country codes we think are important
410         //     (the G7 countries, plus a couple others)?
411         // 3) Does each list have every entry formatted correctly? (i.e., two characters,
412         //     all lower case for the language codes, all upper case for the country codes)
413         // 4) Is each list in sorted order?
414         String[] test = Locale.getISOLanguages();
415         String[] spotCheck1 = { "en", "es", "fr", "de", "it", "ja", "ko", "zh", "th",
416                                 "he", "id", "iu", "ug", "yi", "za" };
417 
418         if (test.length != 188)
419             errln("Expected getISOLanguages() to return 188 languages; it returned " + test.length);
420         else {
421             for (int i = 0; i < spotCheck1.length; i++) {
422                 int j;
423                 for (j = 0; j < test.length; j++)
424                     if (test[j].equals(spotCheck1[i]))
425                         break;
426                 if (j == test.length || !test[j].equals(spotCheck1[i]))
427                     errln("Couldn't find " + spotCheck1[i] + " in language list.");
428             }
429         }
430         for (int i = 0; i < test.length; i++) {
431             if (!test[i].equals(test[i].toLowerCase()))
432                 errln(test[i] + " is not all lower case.");
433             if (test[i].length() != 2)
434                 errln(test[i] + " is not two characters long.");
435             if (i > 0 && test[i].compareTo(test[i - 1]) <= 0)
436                 errln(test[i] + " appears in an out-of-order position in the list.");
437         }
438 
439         test = Locale.getISOCountries();
440         String[] spotCheck2 = { "US", "CA", "GB", "FR", "DE", "IT", "JP", "KR", "CN", "TW", "TH" };
441 
442 
443         if (test.length != 246)
444             errln("Expected getISOCountries to return 246 countries; it returned " + test.length);
445         else {
446             for (int i = 0; i < spotCheck2.length; i++) {
447                 int j;
448                 for (j = 0; j < test.length; j++)
449                     if (test[j].equals(spotCheck2[i]))
450                         break;
451                 if (j == test.length || !test[j].equals(spotCheck2[i]))
452                     errln("Couldn't find " + spotCheck2[i] + " in country list.");
453             }
454         }
455         for (int i = 0; i < test.length; i++) {
456             if (!test[i].equals(test[i].toUpperCase()))
457                 errln(test[i] + " is not all upper case.");
458             if (test[i].length() != 2)
459                 errln(test[i] + " is not two characters long.");
460             if (i > 0 && test[i].compareTo(test[i - 1]) <= 0)
461                 errln(test[i] + " appears in an out-of-order position in the list.");
462         }
463     }
464 
465     /**
466      * @bug 4126880
467      */
468     void Test4126880() {
469         String[] test;
470 
471         test = Locale.getISOCountries();
472         test[0] = "SUCKER!!!";
473         test = Locale.getISOCountries();
474         if (test[0].equals("SUCKER!!!"))
475             errln("Changed internal country code list!");
476 
477         test = Locale.getISOLanguages();
478         test[0] = "HAHAHAHA!!!";
479         test = Locale.getISOLanguages();
480         if (test[0].equals("HAHAHAHA!!!")) // Fixed typo
481             errln("Changes internal language code list!");
482     }
483 
484     /**
485      * @bug 4107014
486      */
487     public void TestGetAvailableLocales() {
488         Locale[] locales = Locale.getAvailableLocales();
489         if (locales == null || locales.length == 0)
490             errln("Locale.getAvailableLocales() returned no installed locales!");
491         else {
492             logln("Locale.getAvailableLocales() returned a list of " + locales.length + " locales.");
493             for (int i = 0; i < locales.length; i++)
494                 logln(locales[i].toString());
495         }
496     }
497 
498     /**
499      * @bug 4135316
500      */
501     public void TestBug4135316() {
502         Locale[] locales1 = Locale.getAvailableLocales();
503         Locale[] locales2 = Locale.getAvailableLocales();
504         if (locales1 == locales2)
505             errln("Locale.getAvailableLocales() doesn't clone its internal storage!");
506     }
507 
508     /**
509      * @bug 4107953
510      */
511 /*
512 test commented out pending API-change approval
513     public void TestGetLanguagesForCountry() {
514         String[] languages = Locale.getLanguagesForCountry("US");
515 
516         if (!searchStringArrayFor("en", languages))
517             errln("Didn't get en as a language for US");
518 
519         languages = Locale.getLanguagesForCountry("FR");
520         if (!searchStringArrayFor("fr", languages))
521             errln("Didn't get fr as a language for FR");
522 
523         languages = Locale.getLanguagesForCountry("CH");
524         if (!searchStringArrayFor("fr", languages))
525             errln("Didn't get fr as a language for CH");
526         if (!searchStringArrayFor("it", languages))
527             errln("Didn't get it as a language for CH");
528         if (!searchStringArrayFor("de", languages))
529             errln("Didn't get de as a language for CH");
530 
531         languages = Locale.getLanguagesForCountry("JP");
532         if (!searchStringArrayFor("ja", languages))
533             errln("Didn't get ja as a language for JP");
534     }
535 */
536 
537     private boolean searchStringArrayFor(String s, String[] array) {
538         for (int i = 0; i < array.length; i++)
539             if (s.equals(array[i]))
540                 return true;
541         return false;
542     }
543     /**
544      * @bug 4110613
545      */
546     public void TestSerialization() throws ClassNotFoundException, OptionalDataException,
547                     IOException, StreamCorruptedException
548     {
549         ObjectOutputStream ostream;
550         ByteArrayOutputStream obstream;
551         byte[] bytes = null;
552 
553         obstream = new ByteArrayOutputStream();
554         ostream = new ObjectOutputStream(obstream);
555 
556         Locale test1 = new Locale("zh", "TW", "");
557         int dummy = test1.hashCode();   // fill in the cached hash-code value
558         ostream.writeObject(test1);
559 
560         bytes = obstream.toByteArray();
561 
562         ObjectInputStream istream = new ObjectInputStream(new ByteArrayInputStream(bytes));
563 
564         Locale test2 = (Locale)(istream.readObject());
565 
566         if (!test1.equals(test2) || test1.hashCode() != test2.hashCode())
567             errln("Locale failed to deserialize correctly.");
568     }
569 
570     /**
571      * @bug 4118587
572      */
573     public void TestSimpleDisplayNames() {
574         // This test is different from TestDisplayNames because TestDisplayNames checks
575         // fallback behavior, combination of language and country names to form locale
576         // names, and other stuff like that.  This test just checks specific language
577         // and country codes to make sure we have the correct names for them.
578         String[] languageCodes = { "he", "id", "iu", "ug", "yi", "za" };
579         String[] languageNames = { "Hebrew", "Indonesian", "Inuktitut", "Uighur", "Yiddish",
580                                    "Zhuang" };
581 
582         for (int i = 0; i < languageCodes.length; i++) {
583             String test = (new Locale(languageCodes[i], "", "")).getDisplayLanguage(Locale.US);
584             if (!test.equals(languageNames[i]))
585                 errln("Got wrong display name for " + languageCodes[i] + ": Expected \"" +
586                       languageNames[i] + "\", got \"" + test + "\".");
587         }
588     }
589 
590     /**
591      * @bug 4118595
592      */
593     public void TestUninstalledISO3Names() {
594         // This test checks to make sure getISO3Language and getISO3Country work right
595         // even for locales that are not installed.
596         String[] iso2Languages = { "am", "ba", "fy", "mr", "rn", "ss", "tw", "zu" };
597         String[] iso3Languages = { "amh", "bak", "fry", "mar", "run", "ssw", "twi", "zul" };
598 
599         for (int i = 0; i < iso2Languages.length; i++) {
600             String test = (new Locale(iso2Languages[i], "", "")).getISO3Language();
601             if (!test.equals(iso3Languages[i]))
602                 errln("Got wrong ISO3 code for " + iso2Languages[i] + ": Expected \"" +
603                         iso3Languages[i] + "\", got \"" + test + "\".");
604         }
605 
606         String[] iso2Countries = { "AF", "BW", "KZ", "MO", "MN", "SB", "TC", "ZW" };
607         String[] iso3Countries = { "AFG", "BWA", "KAZ", "MAC", "MNG", "SLB", "TCA", "ZWE" };
608 
609         for (int i = 0; i < iso2Countries.length; i++) {
610             String test = (new Locale("", iso2Countries[i], "")).getISO3Country();
611             if (!test.equals(iso3Countries[i]))
612                 errln("Got wrong ISO3 code for " + iso2Countries[i] + ": Expected \"" +
613                         iso3Countries[i] + "\", got \"" + test + "\".");
614         }
615     }
616 
617     /**
618      * @bug 4052404 4778440
619      */
620     public void TestChangedISO639Codes() {
621         Locale hebrewOld = new Locale("iw", "IL", "");
622         Locale hebrewNew = new Locale("he", "IL", "");
623         Locale yiddishOld = new Locale("ji", "IL", "");
624         Locale yiddishNew = new Locale("yi", "IL", "");
625         Locale indonesianOld = new Locale("in", "", "");
626         Locale indonesianNew = new Locale("id", "", "");
627 
628         if (!hebrewNew.getLanguage().equals("iw"))
629             errln("Got back wrong language code for Hebrew: expected \"iw\", got \"" +
630                             hebrewNew.getLanguage() + "\"");
631         if (!yiddishNew.getLanguage().equals("ji"))
632             errln("Got back wrong language code for Yiddish: expected \"ji\", got \"" +
633                             yiddishNew.getLanguage() + "\"");
634         if (!indonesianNew.getLanguage().equals("in"))
635             errln("Got back wrong language code for Indonesian: expected \"in\", got \"" +
636                             indonesianNew.getLanguage() + "\"");
637     }
638 
639     /**
640      * @bug 4092475
641      * I could not reproduce this bug.  I'm pretty convinced it was fixed with the
642      * big locale-data reorg of 10/28/97.  The lookup logic for language and country
643      * display names was also changed at that time in that check-in.    --rtg 3/20/98
644 
645      * This test is not designed to work in any other locale but en_US.
646      * Most of the LocaleElements do not contain display names for other languages,
647      * so this test fails (bug 4289223) when run under different locales. For example,
648      * LocaleElements_es as of kestrel does not have a localized name for Japanese, so
649      * the getDisplayName method asks the default locale for a display name. The Japanese
650      * localized name for "Japanese" does not equal "Japanese" so this test fails for es
651      * display names if run under a ja locale. Eventually, he LocaleElements should probably
652      * be updated to contain more localized language and region display names.
653      * 1999-11-19 joconner
654      *
655      */
656     public void TestAtypicalLocales() {
657         Locale[] localesToTest = { new Locale("de", "CA"),
658                                    new Locale("ja", "ZA"),
659                                    new Locale("ru", "MX"),
660                                    new Locale("en", "FR"),
661                                    new Locale("es", "DE"),
662                                    new Locale("", "HR"),
663                                    new Locale("", "SE"),
664                                    new Locale("", "DO"),
665                                    new Locale("", "BE") };
666         String[] englishDisplayNames = { "German (Canada)",
667                                          "Japanese (South Africa)",
668                                          "Russian (Mexico)",
669                                          "English (France)",
670                                          "Spanish (Germany)",
671                                          "Croatia",
672                                          "Sweden",
673                                          "Dominican Republic",
674                                          "Belgium" };
675         String[] frenchDisplayNames = { "allemand (Canada)",
676                                         "japonais (Afrique du Sud)",
677                                         "russe (Mexique)",
678                                          "anglais (France)",
679                                          "espagnol (Allemagne)",
680                                         "Croatie",
681                                         "Su\u00e8de",
682                                         "R\u00e9publique Dominicaine",
683                                         "Belgique" };
684         String[] spanishDisplayNames = { "alem\u00E1n (Canad\u00E1)",
685                                          "japon\u00E9s (Sud\u00E1frica)",
686                                          "ruso (M\u00e9xico)",
687                                          "ingl\u00E9s (Francia)",
688                                          "espa\u00f1ol (Alemania)",
689                                          "Croacia",
690                                          "Suecia",
691                                          "Rep\u00fablica Dominicana",
692                                          "B\u00E9lgica" };
693 
694 
695         // save the default locale and set to the new default to en_US
696         Locale defaultLocale = Locale.getDefault();
697         Locale.setDefault(Locale.US);
698 
699         for (int i = 0; i < localesToTest.length; i++) {
700             String name = localesToTest[i].getDisplayName(Locale.US);
701             logln(name);
702             if (!name.equals(englishDisplayNames[i]))
703                 errln("Lookup in English failed: expected \"" + englishDisplayNames[i]
704                             + "\", got \"" + name + "\"");
705         }
706 
707         for (int i = 0; i < localesToTest.length; i++) {
708             String name = localesToTest[i].getDisplayName(new Locale("es", "ES"));
709             logln(name);
710             if (!name.equals(spanishDisplayNames[i]))
711                 errln("Lookup in Spanish failed: expected \"" + spanishDisplayNames[i]
712                             + "\", got \"" + name + "\"");
713         }
714 
715         for (int i = 0; i < localesToTest.length; i++) {
716             String name = localesToTest[i].getDisplayName(Locale.FRANCE);
717             logln(name);
718             if (!name.equals(frenchDisplayNames[i]))
719                 errln("Lookup in French failed: expected \"" + frenchDisplayNames[i]
720                             + "\", got \"" + name + "\"");
721         }
722 
723         // restore the default locale for other tests
724         Locale.setDefault(defaultLocale);
725     }
726 
727     /**
728      * @bug 4126371
729      */
730     public void TestNullDefault() {
731         // why on earth anyone would ever try to do this is beyond me, but we should
732         // definitely make sure we don't let them
733         boolean gotException = false;
734         try {
735             Locale.setDefault(null);
736         }
737         catch (NullPointerException e) {
738             // all other exception types propagate through here back to the test harness
739             gotException = true;
740         }
741         if (Locale.getDefault() == null)
742             errln("Locale.getDefault() allowed us to set default to NULL!");
743         if (!gotException)
744             errln("Trying to set default locale to NULL didn't throw exception!");
745     }
746 
747     /**
748      * @bug 4135752
749      * This would be better tested by the LocaleDataTest.  Will move it when I
750      * get the LocaleDataTest working again.
751      */
752     public void TestThaiCurrencyFormat() {
753         DecimalFormat thaiCurrency = (DecimalFormat)NumberFormat.getCurrencyInstance(
754                         new Locale("th", "TH"));
755         if (!thaiCurrency.getPositivePrefix().equals("\u0e3f"))
756             errln("Thai currency prefix wrong: expected \"\u0e3f\", got \"" +
757                             thaiCurrency.getPositivePrefix() + "\"");
758         if (!thaiCurrency.getPositiveSuffix().equals(""))
759             errln("Thai currency suffix wrong: expected \"\", got \"" +
760                             thaiCurrency.getPositiveSuffix() + "\"");
761     }
762 
763     /**
764      * @bug 4122371
765      * Confirm that Euro support works.  This test is pretty rudimentary; all it does
766      * is check that any locales with the EURO variant format a number using the
767      * Euro currency symbol.
768      *
769      * ASSUME: All locales encode the Euro character "\u20AC".
770      * If this is changed to use the single-character Euro symbol, this
771      * test must be updated.
772      *
773      * DON'T ASSUME: Any specific countries support the Euro.  Instead,
774      * iterate through all locales.
775      */
776     public void TestEuroSupport() {
777         final String EURO_VARIANT  = "EURO";
778         final String EURO_CURRENCY = "\u20AC"; // Look for this string in formatted Euro currency
779 
780         Locale[] locales = NumberFormat.getAvailableLocales();
781         for (int i=0; i<locales.length; ++i) {
782             Locale loc = locales[i];
783             if (loc.getVariant().indexOf(EURO_VARIANT) >= 0) {
784                 NumberFormat nf = NumberFormat.getCurrencyInstance(loc);
785                 String pos = nf.format(271828.182845);
786                 String neg = nf.format(-271828.182845);
787                 if (pos.indexOf(EURO_CURRENCY) >= 0 &&
788                     neg.indexOf(EURO_CURRENCY) >= 0) {
789                     logln("Ok: " + loc.toString() +
790                           ": " + pos + " / " + neg);
791                 }
792                 else {
793                     errln("Fail: " + loc.toString() +
794                           " formats without " + EURO_CURRENCY +
795                           ": " + pos + " / " + neg +
796                           "\n*** THIS FAILURE MAY ONLY MEAN THAT LOCALE DATA HAS CHANGED ***");
797                 }
798             }
799         }
800     }
801 
802     /**
803      * @bug 4139504
804      * toString() doesn't work with language_VARIANT.
805      */
806     public void TestToString() {
807         Object[] DATA = {
808             new Locale("xx", "", ""), "xx",
809             new Locale("", "YY", ""), "_YY",
810         new Locale("", "", "ZZ"), "",
811             new Locale("xx", "YY", ""), "xx_YY",
812             new Locale("xx", "", "ZZ"), "xx__ZZ",
813             new Locale("", "YY", "ZZ"), "_YY_ZZ",
814             new Locale("xx", "YY", "ZZ"), "xx_YY_ZZ",
815         };
816         for (int i=0; i<DATA.length; i+=2) {
817             Locale loc = (Locale)DATA[i];
818             String fmt = (String)DATA[i+1];
819             if (!loc.toString().equals(fmt)) {
820                 errln("Fail: Locale.toString(" + fmt + ")=>" + loc);
821             }
822         }
823     }
824 
825     /**
826      * @bug 4105828
827      * Currency symbol in zh is wrong.  We will test this at the NumberFormat
828      * end to test the whole pipe.
829      */
830     public void Test4105828() {
831         Locale[] LOC = { Locale.CHINESE, new Locale("zh", "CN", ""),
832                          new Locale("zh", "TW", ""), new Locale("zh", "HK", "") };
833         for (int i=0; i<LOC.length; ++i) {
834             NumberFormat fmt = NumberFormat.getPercentInstance(LOC[i]);
835             String result = fmt.format(1);
836             if (!result.equals("100%")) {
837                 errln("Percent for " + LOC[i] + " should be 100%, got " + result);
838             }
839         }
840     }
841 
842     /**
843      * @bug 4139940
844      * Couldn't reproduce this bug -- probably was fixed earlier.
845      *
846      * ORIGINAL BUG REPORT:
847      * -- basically, hungarian for monday shouldn't have an \u00f4
848      * (o circumflex)in it instead it should be an o with 2 inclined
849      * (right) lines over it..
850      *
851      * You may wonder -- why do all this -- why not just add a line to
852      * LocaleData?  Well, I could see by inspection that the locale file had the
853      * right character in it, so I wanted to check the rest of the pipeline -- a
854      * very remote possibility, but I wanted to be sure.  The other possibility
855      * is that something is wrong with the font mapping subsystem, but we can't
856      * test that here.
857      */
858     public void Test4139940() {
859         Locale mylocale=new Locale("hu", "", "");
860         Date mydate = new Date(98,3,13); // A Monday
861         DateFormat df_full = new SimpleDateFormat("EEEE", mylocale);
862         String str = df_full.format(mydate);
863         // Make sure that o circumflex (\u00F4) is NOT there, and
864         // o double acute (\u0151) IS.
865         if (str.indexOf('\u0151') < 0 || str.indexOf('\u00F4') >= 0)
866             errln("Fail: Monday in Hungarian is wrong");
867     }
868 
869     /**
870      * @bug 4143951
871      * Russian first day of week should be Monday. Confirmed.
872      */
873     public void Test4143951() {
874         Calendar cal = Calendar.getInstance(new Locale("ru", "", ""));
875         if (cal.getFirstDayOfWeek() != Calendar.MONDAY) {
876             errln("Fail: First day of week in Russia should be Monday");
877         }
878     }
879 
880     /**
881      * @bug 4147315
882      * java.util.Locale.getISO3Country() works wrong for non ISO-3166 codes.
883      * Should throw an exception for unknown locales
884      */
885     public void Test4147315() {
886         // Try with codes that are the wrong length but happen to match text
887         // at a valid offset in the mapping table
888         Locale locale = new Locale("aaa", "CCC");
889 
890         try {
891             String result = locale.getISO3Country();
892 
893             errln("ERROR: getISO3Country() returns: " + result +
894                 " for locale '" + locale + "' rather than exception" );
895         } catch(MissingResourceException e) { }
896     }
897 
898     /**
899      * @bug 4147317 4940539
900      * java.util.Locale.getISO3Language() works wrong for non ISO-639 codes.
901      * Should throw an exception for unknown locales, except they have three
902      * letter language codes.
903      */
904     public void Test4147317() {
905         // Try a three letter language code, and check whether it is
906         // returned as is.
907         Locale locale = new Locale("aaa", "CCC");
908 
909         String result = locale.getISO3Language();
910         if (!result.equals("aaa")) {
911             errln("ERROR: getISO3Language() returns: " + result +
912                 " for locale '" + locale + "' rather than returning it as is" );
913         }
914 
915         // Try an invalid two letter language code, and check whether it
916         // throws a MissingResourceException.
917         locale = new Locale("zz", "CCC");
918 
919         try {
920             result = locale.getISO3Language();
921 
922             errln("ERROR: getISO3Language() returns: " + result +
923                 " for locale '" + locale + "' rather than exception" );
924         } catch(MissingResourceException e) { }
925     }
926 
927     /*
928      * @bug 4147552 4778440
929      */
930     public void Test4147552() {
931         Locale[] locales = { new Locale("no", "NO"), new Locale("no", "NO", "B"),
932                              new Locale("no", "NO", "NY") };
933         String[] englishDisplayNames = { "Norwegian (Norway)",
934                      "Norwegian (Norway,Bokm\u00e5l)",
935                      "Norwegian (Norway,Nynorsk)" };
936         String[] norwegianDisplayNames = { "norsk (Norge)",
937                      "norsk (Norge,bokm\u00e5l)", "norsk (Norge,nynorsk)" };
938 
939         for (int i = 0; i < locales.length; i++) {
940             Locale loc = locales[i];
941             if (!loc.getDisplayName(Locale.US).equals(englishDisplayNames[i]))
942                errln("English display-name mismatch: expected " +
943                        englishDisplayNames[i] + ", got " + loc.getDisplayName());
944             if (!loc.getDisplayName(loc).equals(norwegianDisplayNames[i]))
945                 errln("Norwegian display-name mismatch: expected " +
946                        norwegianDisplayNames[i] + ", got " +
947                        loc.getDisplayName(loc));
948         }
949     }
950 
951     static String escapeUnicode(String s) {
952         StringBuffer buf = new StringBuffer();
953         for (int i=0; i<s.length(); ++i) {
954             char c = s.charAt(i);
955             if (c >= 0x20 && c <= 0x7F) buf.append(c);
956             else {
957                 buf.append("\\u");
958                 String h = "000" + Integer.toHexString(c);
959                 if (h.length() > 4) h = h.substring(h.length() - 4);
960                 buf.append(h);
961             }
962         }
963         return buf.toString();
964     }
965 }